package com.xdog.okx.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xdog.okx.config.OkxConfig;
import com.xdog.okx.exception.OkxApiError;
import com.xdog.okx.exception.OkxApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * OKX API工具类
 * 提供静态方法调用OKX API，方便在任何地方使用
 */
@Slf4j
@Component
public class OkxApiUtil {

    private static OkxConfig okxConfigService;

    @Autowired
    public void setOkxConfigService(OkxConfig okxConfigService) {
        OkxApiUtil.okxConfigService = okxConfigService;
    }

    /**
     * 发送GET请求
     *
     * @param requestPath  请求路径
     * @param queryParams  查询参数
     * @return 响应结果
     */
    public static JSONObject get(String requestPath, Map<String, String> queryParams) {
        // 构建完整URL
        StringBuilder urlBuilder = new StringBuilder(okxConfigService.getBaseUrl());
        urlBuilder.append(requestPath);

        if (queryParams != null && !queryParams.isEmpty()) {
            urlBuilder.append("?");
            boolean first = true;
            for (Map.Entry<String, String> entry : queryParams.entrySet()) {
                if (!first) {
                    urlBuilder.append("&");
                }
                urlBuilder.append(entry.getKey()).append("=").append(entry.getValue());
                first = false;
            }
        }

        String fullUrl = urlBuilder.toString();
        return executeRequest("GET", requestPath, fullUrl, "");
    }

    /**
     * 发送POST请求
     *
     * @param requestPath 请求路径
     * @param body        请求体
     * @return 响应结果
     */
    public static JSONObject post(String requestPath, Object body) {
        String fullUrl = okxConfigService.getBaseUrl() + requestPath;
        String bodyStr = body != null ? JSON.toJSONString(body) : "";
        return executeRequest("POST", requestPath, fullUrl, bodyStr);
    }

    /**
     * 执行HTTP请求的通用方法
     *
     * @param method     HTTP方法 (GET/POST)
     * @param requestPath 请求路径（用于签名）
     * @param fullUrl    完整URL
     * @param body       请求体（仅POST请求需要）
     * @return           响应结果
     */
    private static JSONObject executeRequest(String method, String requestPath, String fullUrl, String body) {
        try {
            log.info("准备发送OKX {}请求: {}", method, fullUrl);

            URL url = new URL(fullUrl);

            // 创建HTTP连接，支持代理设置
            HttpURLConnection connection = createHttpConnection(url);

            connection.setRequestMethod(method);
            connection.setConnectTimeout(okxConfigService.getConnectTimeout());
            connection.setReadTimeout(okxConfigService.getReadTimeout());

            if ("POST".equals(method)) {
                connection.setDoOutput(true);
            }

            // 添加一些HTTP连接属性以提高兼容性
            connection.setRequestProperty("Connection", "close");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");

            // 设置请求头
            Map<String, String> headers = OkxSignatureUtils.generateAuthHeaders(
                okxConfigService.getApiKey(),
                okxConfigService.getSecretKey(),
                okxConfigService.getPassphrase(),
                method,
                requestPath,
                body
            );
            
            // 记录请求头信息用于调试
            log.debug("API密钥是否存在: {}, 密钥是否存在: {}, Passphrase是否存在: {}",
                okxConfigService.getApiKey() != null && !okxConfigService.getApiKey().isEmpty(),
                okxConfigService.getSecretKey() != null && !okxConfigService.getSecretKey().isEmpty(),
                okxConfigService.getPassphrase() != null && !okxConfigService.getPassphrase().isEmpty());
            
            log.debug("请求头信息:");
            for (Map.Entry<String, String> header : headers.entrySet()) {
                // 避免记录敏感信息
                if (!"OK-ACCESS-KEY".equals(header.getKey()) && 
                    !"OK-ACCESS-SIGN".equals(header.getKey()) && 
                    !"OK-ACCESS-PASSPHRASE".equals(header.getKey())) {
                    log.debug("{}: {}", header.getKey(), header.getValue());
                } else {
                    log.debug("{}: [已隐藏敏感信息]", header.getKey());
                }
            }

            for (Map.Entry<String, String> header : headers.entrySet()) {
                connection.setRequestProperty(header.getKey(), header.getValue());
            }

            // 写入请求体（仅POST请求）
            if ("POST".equals(method) && body != null) {
                try (OutputStream os = connection.getOutputStream()) {
                    byte[] input = body.getBytes(StandardCharsets.UTF_8);
                    os.write(input, 0, input.length);
                }
            }

            // 读取响应
            int responseCode = connection.getResponseCode();
            log.info("OKX {}请求响应码: {}", method, responseCode);

            // 读取响应内容
            StringBuilder response = new StringBuilder();
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(
                responseCode >= 200 && responseCode < 300 ?
                    connection.getInputStream() :
                    connection.getErrorStream(),
                StandardCharsets.UTF_8))) {

                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
            }

            String responseStr = response.toString();

            // 解析响应结果
            JSONObject result = JSON.parseObject(responseStr);

            // 检查是否有错误码
            if (result.containsKey("code") && !result.getString("code").equals("0")) {
                String errorCode = result.getString("code");
                String errorMsg = result.getString("msg");
                OkxApiError error = OkxApiError.findByCode(errorCode);

                if (error != null) {
                    log.error("OKX API返回错误: code={}, message={}, httpStatus={}",
                        errorCode, errorMsg, error.getHttpStatus());
                    throw new OkxApiException(errorCode, error.getHttpStatus(),
                        "API错误: " + errorMsg);
                } else {
                    log.error("OKX API返回未知错误: code={}, message={}", errorCode, errorMsg);
                    throw new OkxApiException(errorCode, 400,
                        "API未知错误: " + errorMsg);
                }
            }

            log.info("OKX {}请求处理完成", method);
            return result;
        } catch (OkxApiException e) {
            log.error("OKX API {}请求失败: {}", method, e.getMessage(), e);
            throw e;
        } catch (Exception e) {
            log.error("OKX API {}请求失败: {}", method, e.getMessage(), e);
            throw new RuntimeException("OKX API请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建HTTP连接，支持代理设置
     *
     * @param url 目标URL
     * @return HttpURLConnection对象
     */
    private static HttpURLConnection createHttpConnection(URL url) {
        try {
            String proxyHost = okxConfigService.getProxyHost();
            Integer proxyPort = okxConfigService.getProxyPort();

            if (proxyHost != null && !proxyHost.isEmpty() && proxyPort != null) {
                log.debug("使用代理: {}:{}", proxyHost, proxyPort);
                Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
                return (HttpURLConnection) url.openConnection(proxy);
            } else {
                return (HttpURLConnection) url.openConnection();
            }
        } catch (Exception e) {
            throw new RuntimeException("创建HTTP连接失败: " + e.getMessage(), e);
        }
    }
}
